using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Windows.Forms;
using Microsoft.Practices.RecipeFramework.Library;
using Microsoft.VisualStudio.Shell.Design;
using Microsoft.VisualStudio.Shell.Interop;

namespace VSSDKAssist.Recipes.Common.Editors.Grid
{
    /// <summary>
    /// DataGridView column to collect types supporting autocomplete
    /// </summary>
    public class TypeColumn : DesignerColumn
    {
        private AutoCompleteStringCollection autoCompleteSource;

        public TypeColumn()
            : base(new TypeColumnCell())
        {
        }

        protected TypeColumn(DataGridViewCell template)
            : base(template)
        {
        }

        /// <summary>
        /// Overriding this method can filter the types shown for autocomplete
        /// </summary>
        /// <param name="type">The type to accept or reject</param>
        /// <returns>The default value is true</returns>
        protected virtual bool AcceptType(Type type)
        {
            return true;
        }

        /// <summary>
        /// Returns the discovered types for autocomplete
        /// </summary>
        protected virtual IEnumerable<Type> DiscoverTypes()
        {
            DynamicTypeService typeService = (DynamicTypeService)DataGridView.Site.GetService(typeof(DynamicTypeService));
            IVsHierarchy hier = DteHelper.GetCurrentSelection(DataGridView.Site);
            ITypeDiscoveryService typeDiscoveryService = typeService.GetTypeDiscoveryService(hier);

            return (IEnumerable<Type>)typeDiscoveryService.GetTypes(typeof(object), false);
        }

        /// <summary>
        /// Creates the <see cref="AutoCompleteStringCollection"/> with all the types
        /// </summary>
        private AutoCompleteStringCollection GetAutocompleteSource()
        {
            if(autoCompleteSource == null)
            {
                List<string> types = new List<string>();

                foreach(Type type in DiscoverTypes())
                {
                    if(AcceptType(type))
                        types.Add(type.FullName);
                }

                autoCompleteSource = new AutoCompleteStringCollection();
                autoCompleteSource.AddRange(types.ToArray());
            }

            return autoCompleteSource;
        }

        public class TypeColumnCell : DesignerColumn.DesignerCell
        {
            public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
            {
                base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);

                TextBox textBox = DataGridView.EditingControl as TextBox;
                if(textBox != null)
                {
                    // Setup textbox autocomplete
                    textBox.AutoCompleteCustomSource = ((TypeColumn)OwningColumn).GetAutocompleteSource();
                    textBox.AutoCompleteMode = AutoCompleteMode.Suggest;
                    textBox.AutoCompleteSource = AutoCompleteSource.CustomSource;
                }
            }

            public override void DetachEditingControl()
            {
                TextBox textBox = DataGridView.EditingControl as TextBox;
                if(textBox != null)
                {
                    textBox.AutoCompleteCustomSource = null;
                    textBox.AutoCompleteMode = AutoCompleteMode.None;
                    textBox.AutoCompleteSource = AutoCompleteSource.None;
                }
                base.DetachEditingControl();
            }
        }
    }
}
